#pragma once 
#include <vector>
#include <cassert>

//单点信息结构体
typedef struct OnePointInfo
{
    unsigned short line_id = 0;                 //线号 1-144
    unsigned short rotating_mirror_id = 0;      //转镜号
    unsigned short ld_id = 0;                   //LD号 1-48
    double azimuth = 0;                         //方位角 (0~360)*100
    double vazimuth = 0;
    double h_angle = 0;                         // 协议里的原始角度
    double v_angle = 0;                         // 垂直角度
    unsigned int old_distance = 0;
    unsigned int distance = 0;                  //距离(毫米)
    unsigned char intensity = 0;                //反射率
    unsigned short low_thres_pulsewidth = 0;    // 低阈值脉宽
    unsigned short high_thres_pulsewidth= 0;    // 高阈值脉宽
    unsigned int index = 0;                 //此点在1圈数据中的位置，通过方位角获取当前包所在标号.eg:732/10HZ:包数（0~179）*10*32+块数(0~9)*32+线数(0~31);
    int echo_type = 0;                      //回波类型 1- 最强 2最后
    double time = 0;
    int ground_flag = 0;                    // 地面点标志
    int ghost_flag = 0;                     // 鬼影标志
    int strong_weak = 0;                    // 强弱发光标志 0：弱 1：强
    int label = 0;                          // 聚类标签
    int scanindex = -1;                     // 网格索引点
    int scanline = -1;
    unsigned int src_index = -1;            //  原始索引
    double x = 0;							//x轴坐标，单位米
    double y = 0;							//y轴坐标，单位米
    double z = 0;							//z轴坐标，单位米
    int blank_point_compen = 0;
    int _40_blank_point_compen = 0;
    int non_filterable = 0;                 // 0-不显示该点 1-显示该点
    int expansion = 0;
    int close_range_outliers = 0;           // 0-不显示该点 1-显示该点
    float r = 0;//R/255
    float g = 0;//G/255
    float b = 0;//B/255
}OnePointInfo;


class ItIntexRecord
{
public:
    long long index_record_ = -1;
    long long it_strong_index_record_ = -1;
    long long it_last_index_record_ = -1;
};

class OnePointInfoManage
{
private:
    std::vector<OnePointInfo> strong_point_data_;
    std::vector<std::vector<long>> strong_point_dataI_index_;


    std::vector<OnePointInfo> last_point_data_;
    std::vector<std::vector<long>> last_point_data_index_;

    int line_count_ = 0;

    std::vector<ItIntexRecord> it_index_records_;

public:
    size_t strong_point_data_size_ = 0;
    size_t last_point_data_size_ = 0;

    // 由于采用size_t size() const;函数获取size会导致创建堆栈的耗时 因此将indexRecordsize设置为全局变量
    size_t index_record_size_ = 0; 
    OnePointInfoManage();
    ~OnePointInfoManage();
    OnePointInfoManage(int line_id);
    // 复制构造函数
    OnePointInfoManage(const OnePointInfoManage& s);
    OnePointInfoManage(OnePointInfoManage&& s);
    // 等于号重载
    OnePointInfoManage& operator= (const OnePointInfoManage& s);
    OnePointInfoManage& operator= (OnePointInfoManage&& s);

    void Init(int line_id);
    void insert(unsigned int index, OnePointInfo& data);
    void insert(unsigned int index, OnePointInfo&& data);
    void CleanLineData(unsigned int line_id);
    // echo_type 0最强一重点云 1最后一重点云    line_id 线号 0- 143 h_angle   水平角度 0-3600
    OnePointInfo& GetData(int echo_type,unsigned int line_id,unsigned int h_angle);
    OnePointInfo& GetData(unsigned int index);
    long GetIndex(int echo_type,unsigned int line_id,unsigned int h_angle);
    //OnePointInfo& GetDataConst(unsigned int index) const;
    OnePointInfo& GetDataIt(unsigned int index);           // 按迭代获取数据
    //uint GetIterationIndex(unsigned int index) const;      // 获取迭代索引号
    //OnePointInfo& GetDataItConst(unsigned int index) const;
    void ResetPointValue(unsigned int index, double x, double y, double z);

    void Clear();
    size_t size() const;
    size_t sizeMax() const;
    std::vector<OnePointInfo>& Getorigndata();
};




//-----------------------------------------------------
OnePointInfoManage::OnePointInfoManage(int line_id)
{
    index_record_size_ = 0;
    strong_point_data_size_ = 0;
    last_point_data_size_ = 0;
    line_count_ = line_id;
}

OnePointInfoManage::OnePointInfoManage()
{
}
OnePointInfoManage::~OnePointInfoManage()
{
}

OnePointInfoManage::OnePointInfoManage(OnePointInfoManage&& s)
{
    strong_point_data_ = std::move(s.strong_point_data_);
    last_point_data_ = std::move(s.last_point_data_);
    strong_point_dataI_index_ = std::move(s.strong_point_dataI_index_);
    last_point_data_index_ = std::move(s.last_point_data_index_);
    it_index_records_ = std::move(s.it_index_records_);
    strong_point_data_size_ = s.strong_point_data_size_;
    last_point_data_size_ = s.last_point_data_size_;
    line_count_ = s.line_count_;
    index_record_size_ = s.index_record_size_;
}

OnePointInfoManage::OnePointInfoManage(const OnePointInfoManage& s)
{
    Init(s.line_count_);
    strong_point_data_ = s.strong_point_data_;
    last_point_data_ = s.last_point_data_;
    strong_point_dataI_index_ = s.strong_point_dataI_index_;
    last_point_data_index_ = s.last_point_data_index_;
    strong_point_data_size_ = s.strong_point_data_size_;
    last_point_data_size_ = s.last_point_data_size_;
    line_count_ = s.line_count_;
    index_record_size_ = s.index_record_size_;
    it_index_records_ = s.it_index_records_;
}

// 等于号重载
OnePointInfoManage& OnePointInfoManage::operator= (const OnePointInfoManage& s){
    Init(s.line_count_);
    strong_point_data_ = s.strong_point_data_;
    last_point_data_ = s.last_point_data_;
    strong_point_dataI_index_ = s.strong_point_dataI_index_;
    last_point_data_index_ = s.last_point_data_index_;
    strong_point_data_size_ = s.strong_point_data_size_;
    last_point_data_size_ = s.last_point_data_size_;
    line_count_ = s.line_count_;
    index_record_size_ = s.index_record_size_;
    it_index_records_ = s.it_index_records_;
    return *this;
}

OnePointInfoManage& OnePointInfoManage::operator= (OnePointInfoManage&& s){
    strong_point_data_ = std::move(s.strong_point_data_);
    last_point_data_ = std::move(s.last_point_data_);
    strong_point_dataI_index_ = std::move(s.strong_point_dataI_index_);
    last_point_data_index_ = std::move(s.last_point_data_index_);
    it_index_records_ = std::move(s.it_index_records_);
    strong_point_data_size_ = s.strong_point_data_size_;
    last_point_data_size_ = s.last_point_data_size_;
    line_count_ = s.line_count_;
    index_record_size_ = s.index_record_size_;
    return *this;
}

void  OnePointInfoManage::Init(int line_id)
{
    //auto start = std::chrono::steady_clock::now();
    for(size_t i = 0;i< 144;i++)
    {
        std::vector<long> v, v2;
        strong_point_dataI_index_.push_back(v);
        last_point_data_index_.push_back(v2);
        for(size_t j = 0; j < 3600;j++)
        {
            strong_point_dataI_index_[i].push_back(-1);
            last_point_data_index_[i].push_back(-1);
        }
    }
    strong_point_data_size_ = 0;
    last_point_data_size_ = 0;
    line_count_ = line_id;
    index_record_size_ = 0;
}

void OnePointInfoManage::Clear()
{
    strong_point_data_.clear();
    last_point_data_.clear();
    strong_point_dataI_index_.clear();
    last_point_data_index_.clear();
    it_index_records_.clear();
    for(size_t i = 0;i< 144;i++)
    {
        std::vector<long> v(3600,-1), v2(3600,-1);

        strong_point_dataI_index_.push_back(v);
        last_point_data_index_.push_back(v2);

//        for(size_t j = 0; j < 3600;j++)
//        {
//            strong_point_dataI_index_[i].push_back(-1);
//            last_point_data_index_[i].push_back(-1);
//        }
    }
    strong_point_data_size_ = 0;
    last_point_data_size_ = 0;
    index_record_size_ = 0;
}


inline void OnePointInfoManage::insert(unsigned int index, OnePointInfo& data)
{
    //Q_ASSERT(PointData);
    if(data.echo_type == 1)
    {
        if(strong_point_dataI_index_[data.line_id - 1][data.h_angle] == -1)
        {
            strong_point_dataI_index_[data.line_id - 1][data.h_angle] = strong_point_data_size_;
            strong_point_data_.push_back(data);
            ItIntexRecord rtem;
            rtem.index_record_ = index_record_size_;
            rtem.it_strong_index_record_ = strong_point_data_.size() - 1;
            it_index_records_.push_back(rtem);
            strong_point_data_size_++;
            index_record_size_++;
        }
        else// 不包含重复插入的数据
        {
            strong_point_data_[strong_point_dataI_index_[data.line_id - 1][data.h_angle]] = data;
        }
    }
    else
    {
        if(last_point_data_index_[data.line_id - 1][data.h_angle] == -1)
        {
            last_point_data_index_[data.line_id - 1][data.h_angle] = last_point_data_size_;
            last_point_data_.push_back(data);
            ItIntexRecord rtem;
            rtem.index_record_ = index_record_size_;
            rtem.it_last_index_record_ = last_point_data_.size() - 1;
            it_index_records_.push_back(rtem);
            last_point_data_size_++;
            index_record_size_++;
        }
        else// 不包含重复插入的数据
        {
            last_point_data_[last_point_data_index_[data.line_id - 1][data.h_angle]] = data;
        }
    }

}
inline void OnePointInfoManage::insert(unsigned int index, OnePointInfo&& data)
{
    if(data.echo_type == 1)
    {
        if(strong_point_dataI_index_[data.line_id - 1][data.h_angle] == -1)
        {
            strong_point_dataI_index_[data.line_id - 1][data.h_angle] = strong_point_data_size_;
            strong_point_data_.push_back(data);
            ItIntexRecord rtem;
            rtem.index_record_ = index_record_size_;
            rtem.it_strong_index_record_ = strong_point_data_.size() - 1;
            it_index_records_.push_back(rtem);
            strong_point_data_size_++;
            index_record_size_++;
        }
        else// 不包含重复插入的数据
        {
            strong_point_data_[strong_point_dataI_index_[data.line_id - 1][data.h_angle]] = data;
        }
    }
    else
    {
        if(last_point_data_index_[data.line_id - 1][data.h_angle] == -1)
        {
            last_point_data_index_[data.line_id - 1][data.h_angle] = last_point_data_size_;
            last_point_data_.push_back(data);
            ItIntexRecord rtem;
            rtem.index_record_ = index_record_size_;
            rtem.it_last_index_record_ = last_point_data_.size() - 1;
            it_index_records_.push_back(rtem);
            last_point_data_size_++;
            index_record_size_++;
        }
        else// 不包含重复插入的数据
        {
            last_point_data_[last_point_data_index_[data.line_id - 1][data.h_angle]] = data;
        }
    }
}

void OnePointInfoManage::ResetPointValue(unsigned int index, double x, double y, double z)
{
    int echo_type = (index >= 144 *3600) ? 2:1;
    int line_id = (echo_type == 1) ? (index / 3600):((index - (144 *3600)) / 3600);
    int h_angle = (echo_type == 1) ? (index % 3600):((index - (144 *3600)) % 3600);

    if(echo_type == 1)
    {
        if(strong_point_dataI_index_[line_id][h_angle] >= 0)
        {
            strong_point_data_[index].x = x;
            strong_point_data_[index].y = y;
            // strong_point_data_[index].z = z;
        }
    }
    else
    {
        if(last_point_data_index_[line_id][h_angle] >= 0)
        {
            last_point_data_[index].x = x;
            last_point_data_[index].y = y;
            // last_point_data_[index].z = z;
        }
    }
}

void OnePointInfoManage::CleanLineData(unsigned int line_id)
{
    assert(line_id-1 < line_count_);

    std::vector<long> v(3600,-1), v2(3600,-1);

//    for(int i = 0; i < 3600;i++)
//    {
//        if(strong_point_dataI_index_[line_id - 1][i] != -1)
//        {
//            for(int j = 0; j <it_index_records_.size();j++)
//            {
//                if(it_index_records_[j].it_strong_index_record_ == strong_point_dataI_index_[line_id - 1][i])
//                {
//                    it_index_records_.removeAt(j);
//                    index_record_size_--;
//                    break;
//                }
//            }
//            strong_point_dataI_index_[line_id - 1][i] = -1;
//        }
//        if(last_point_data_index_[line_id - 1][i] != -1)
//        {
//            for(int j = 0; j <it_index_records_.size();j++)
//            {
//                if(it_index_records_[j].it_last_index_record_ == last_point_data_index_[line_id - 1][i])
//                {
//                    it_index_records_.removeAt(j);
//                    index_record_size_--;
//                    break;
//                }
//            }
//            last_point_data_index_[line_id - 1][i] = -1;
//        }
//    }

    strong_point_dataI_index_[line_id - 1] = (v);
    last_point_data_index_[line_id - 1] = (v2);
}

OnePointInfo res;
inline OnePointInfo& OnePointInfoManage::GetData(int echo_type,unsigned int line_id,unsigned int h_angle)
{
    assert(echo_type < 3);
    assert(line_id-1 < line_count_);
    if(h_angle > 3600)
    {
        int vv = 0;
    }
    assert(h_angle <= 3600);
    if(echo_type == 1)
    {
        if(strong_point_dataI_index_[line_id - 1][h_angle] >= 0)
        {
            return strong_point_data_[strong_point_dataI_index_[line_id-1][h_angle]];
        }
    }
    else
    {
        if(last_point_data_index_[line_id - 1][h_angle] >= 0)
        {
            return last_point_data_[last_point_data_index_[line_id-1][h_angle]];
        }
    }
    return res;
}

inline OnePointInfo& OnePointInfoManage::GetData(unsigned int index)
{
    int echo_type = (index >= 144 *3600) ? 2:1;
    int line_id = (echo_type == 1) ? (index / 3600):((index - (144 *3600)) / 3600);
    int h_angle = (echo_type == 1) ? (index % 3600):((index - (144 *3600)) % 3600);

    if(echo_type == 1)
    {
        if(strong_point_dataI_index_[line_id][h_angle] >= 0)
        {
            return strong_point_data_[strong_point_dataI_index_[line_id][h_angle]];
        }
    }
    else
    {
        if(last_point_data_index_[line_id][h_angle] >= 0)
        {
            return last_point_data_[last_point_data_index_[line_id][h_angle]];
        }
    }
    return res;
}
long OnePointInfoManage::GetIndex(int echo_type,unsigned int line_id,unsigned int h_angle)
{
    assert(echo_type < 3);
    assert(line_id <= line_count_);
    assert(h_angle <= 3600);
    if(echo_type == 1)
    {
        return strong_point_dataI_index_[line_id - 1][h_angle];
    }
    else
    {
        return last_point_data_index_[line_id - 1][h_angle];
    }
    return -1;
}

//uint OnePointInfoManage::GetIndex(unsigned int index)
//{
//    size_t size = PointDataIndex.size();
//    for(size_t i = 0; i < size; i++)
//    {
//        if(PointDataIndex[i] == index)
//        {
//            return i;
//        }
//    }
//    Q_ASSERT(false);
//    return 0;
//}

OnePointInfo& OnePointInfoManage::GetDataIt(unsigned int index)
{
    assert(index < index_record_size_);

    ItIntexRecord rtem = it_index_records_[index];

    if(rtem.it_strong_index_record_ != -1)
    {
        return strong_point_data_[rtem.it_strong_index_record_];
    }
    else if(rtem.it_last_index_record_ != -1)
    {
        return last_point_data_[rtem.it_last_index_record_];
    }

    return res;
}


size_t OnePointInfoManage::size() const
{
    return index_record_size_;
}

std::vector<OnePointInfo>& OnePointInfoManage::Getorigndata()
{
    return strong_point_data_;
}